#pragma once

#include "fxcc/core/graph/common/pch.h"

namespace fxcc::graph::common
{
	enum class ParamType { Float, Bool, Int };

	struct ParamValue
	{
		ParamType type;
		union
		{
			float f;
			bool b;
			int i;
		};

		ParamValue() : type(ParamType::Float), f(0.0f) {}
		ParamValue(float val) : type(ParamType::Float), f(val) {}
		ParamValue(bool val) : type(ParamType::Bool), b(val) {}
		ParamValue(int val) : type(ParamType::Int), i(val) {}
	};

	struct XParams
	{
		std::string newValueName;
		std::map<std::string, ParamValue> values;

		void SetFloat(const std::string& name, float v) { values[name] = ParamValue(v); }
		void SetBool(const std::string& name, bool v) { values[name] = ParamValue(v); }
		void SetInt(const std::string& name, int v) { values[name] = ParamValue(v); }

		float GetFloat(const std::string& name) const { return values.at(name).f; }
		bool GetBool(const std::string& name) const { return values.at(name).b; }
		int GetInt(const std::string& name) const { return values.at(name).i; }

		ParamType GetType(const std::string& name) const { return values.at(name).type; }
	};

	enum class ConditionOp { Greater, Less, Equal, NotEqual };

	struct Condition
	{
		std::string paramName;
		ConditionOp op;
		ParamType paramType;
		float value;

		bool Evaluate(const XParams& params) const
		{
			if (!params.values.count(paramName)) return false;

			const ParamValue& param = params.values.at(paramName);

			switch (paramType)
			{
			case ParamType::Float:
				return Compare(param.f, value);
			case ParamType::Int:
				return Compare((float)param.i, value);
			case ParamType::Bool:
				return Compare((float)param.b, value);
			}

			return false;
		}

	private:
		bool Compare(float lhs, float rhs) const
		{
			switch (op)
			{
			case ConditionOp::Greater:   return lhs > rhs;
			case ConditionOp::Less:      return lhs < rhs;
			case ConditionOp::Equal:     return lhs == rhs;
			case ConditionOp::NotEqual:  return lhs != rhs;
			default:                     return false;
			}
		}
	};

};